package vg.modules.navigator.components;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JMenuItem;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;

import vg.services.data_base_manager.data.graph.Graph;
import vg.services.data_base_manager.data.skeleton.GraphTreeElement;
import vg.services.data_base_manager.interfaces.IModel;
import vg.services.graph_view_manager.interfaces.graph_view.AGraphView;
import vg.services.main_manager.MainManager;
import vg.services.plugin_manager.event_and_request.request.UIRequestAddTab;
import vg.services.user_interface_manager.interfaces.AUserInterface;

/**
 * This class realizes menu item for opening of composition
 * of vertices in new tab.
 * @author tzolotuhin
 */
public class OpenVerticesMenuItem implements IMenuItem {
	private final JMenuItem jItem;
	private final OpenVerticesAction action;
	/**
	 * Constructor.
	 * @param tree - tree of graph nodes.
	 * @param model - main storage.
	 * @param userInterface - main user interface.
	 */
	public OpenVerticesMenuItem(final JTree tree, final IModel model, final AUserInterface userInterface) {		
		this.action = new OpenVerticesAction(tree, model, userInterface);
		this.jItem = new JMenuItem("Open vertices");
		final Icon icon = new ImageIcon("data/resources/textures/vertexBall.png");
		this.jItem.setIcon(icon);
		this.jItem.addActionListener(this.action);
	}
	public JMenuItem getMenuItem() {
		return(this.jItem);
	}
	public boolean isVisible() {
		return(this.action.isVisible());
	}
	public void updateTheme() {
		SwingUtilities.updateComponentTreeUI(this.jItem);
	}
}
/**
 * Opens composition of vertices in new tab.
 * @author tzolotuhin
 */
class OpenVerticesAction implements ActionListener {
	private final JTree tree;
	private final IModel model;
	private final AUserInterface userInterface;
	/**
	 * Constructor.
	 * @param tree - tree of graph nodes.
	 * @param model - main storage.
	 */
	public OpenVerticesAction(final JTree tree, final IModel model, final AUserInterface userInterface) {
		this.tree = tree;
		this.model = model;
		this.userInterface = userInterface;
	}
	/**
	 * Action
	 */
	public void actionPerformed(ActionEvent e) {
		MainManager.log.printDebug("[" + this.getClass().getName()+".actionPerformed] [PROCESS] Openning of composition of vertexes in new tab(from navigator).");
		if(isVisible()) {
			TreePath[] p = this.tree.getSelectionPaths();
			TreeModel tm = this.tree.getModel();
			if(tm == null) {
				MainManager.log.printDebug("[" + this.getClass().getName()+".actionPerformed] [BAD] Openning of composition of vertexes in new tab(from navigator). Model = null.");
				return;
			} else {
				ArrayList<Integer>vertexes = new ArrayList<Integer>();
				for(int i = 0 ; i < p.length ; i++) {
					GraphTreeElement node = ((GraphTreeElement)tm.getRoot()).vg_getNode(p[i]);
					if((node.vg_getType() & GraphTreeElement.DEF_VERTEX_TYPE) > 0) {
						int db_id = node.vg_getVertexId();
						vertexes.add(db_id);
					} else {
						MainManager.log.printDebug("[" + this.getClass().getName()+".actionPerformed] [BAD] Openning of composition of vertexes in new tab(from navigator). Type of node is not DEF_VERTEX.");
						MainManager.windowMessage.warningMessage("Warning: Elements aren't vertex of graph(May be it is tab or tabs).", "Opening of vertexes");
						return;
					}
				}
				Graph ssg = this.model.getSubGraph(vertexes);
				AGraphView igv = MainManager.graphViewManager.newGraphView(ssg);
				UIRequestAddTab req = new UIRequestAddTab(igv);
				this.userInterface.addRequest(req);
			}
		} else {
			MainManager.log.printDebug("[" + this.getClass().getName()+".actionPerformed] [BAD] Openning of composition of vertexes in new tab(from navigator).");
		}
	}
	public boolean isVisible() {
		if(this.tree != null) {
			TreePath[] p = this.tree.getSelectionPaths();
			if(p != null) {
				if(p.length == 1) {
					TreeModel tm = this.tree.getModel();
					if(tm != null) {
						GraphTreeElement node = ((GraphTreeElement)tm.getRoot()).vg_getNode(p[0]);
						if(node != null && (node.vg_getType() & GraphTreeElement.DEF_VERTEX_TYPE) > 0) {
							return true;
						}
					}
				} else if(p.length > 0) {
					TreePath path = p[0].getParentPath();
					if(path != null) {
						TreeModel tm = this.tree.getModel();
						if(tm != null) {
							String s = path.toString();
							boolean check = false; // check all selected nodes, that they have one parent
							for(int i = 0 ; i < p.length ; i++) {
								GraphTreeElement node = ((GraphTreeElement)tm.getRoot()).vg_getNode(p[i]);
								if(!s.equals(p[i].getParentPath().toString()) || node == null || (~node.vg_getType() & GraphTreeElement.DEF_VERTEX_TYPE) != 0) {
									check = true;
									break;
								}
							}
							return !check;
						}
					} 
				}
			}
		}
		return false;
	}
}
